package com.loukou.lkt.lkt.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.loukou.lkt.company.dao.UserDao;
import com.loukou.lkt.company.entity.User;
import com.loukou.lkt.lkt.constant.Urls;
import com.loukou.lkt.lkt.dao.GoodsCostDao;
import com.loukou.lkt.lkt.dao.GoodsDao;
import com.loukou.lkt.lkt.dao.GoodsStockDao;
import com.loukou.lkt.lkt.dao.PoPurchaseOrderDao;
import com.loukou.lkt.lkt.dao.PoPurchaseOrderDetailDao;
import com.loukou.lkt.lkt.dao.StockInOrderDao;
import com.loukou.lkt.lkt.dao.StockInOrderDetailDao;
import com.loukou.lkt.lkt.dao.SupplierDao;
import com.loukou.lkt.lkt.dao.UserSupplierDao;
import com.loukou.lkt.lkt.dao.WarehouseDao;
import com.loukou.lkt.lkt.entity.Goods;
import com.loukou.lkt.lkt.entity.GoodsStock;
import com.loukou.lkt.lkt.entity.OrderOperateLog;
import com.loukou.lkt.lkt.entity.PoPurchaseOrder;
import com.loukou.lkt.lkt.entity.PoPurchaseOrderDetail;
import com.loukou.lkt.lkt.entity.Supplier;
import com.loukou.lkt.lkt.entity.SupplierGoods;
import com.loukou.lkt.lkt.entity.UserSupplier;
import com.loukou.lkt.lkt.entity.Warehouse;
import com.loukou.lkt.lkt.enums.GoodsStockStateEnum;
import com.loukou.lkt.lkt.enums.OrderOperateLogTypeEnum;
import com.loukou.lkt.lkt.enums.PoPurchaseorderStateEnum;
import com.loukou.lkt.lkt.enums.PositionTypeEnum;
import com.loukou.lkt.lkt.enums.SettlementTypeEnum;
import com.loukou.lkt.lkt.enums.StockInOrderTypeEnum;
import com.loukou.lkt.lkt.enums.SupplierIsExamineEnum;
import com.loukou.lkt.lkt.enums.SupplierIsInUseEnum;
import com.loukou.lkt.lkt.enums.VoucherPrefixEnum;
import com.loukou.lkt.lkt.req.PoPurchaseOrderDetailReqDto;
import com.loukou.lkt.lkt.req.PurchaseOrderDetailDto;
import com.loukou.lkt.lkt.req.PurchaseOrderReqDto;
import com.loukou.lkt.lkt.req.WmsInOrderCallbackDetailReq;
import com.loukou.lkt.lkt.req.WmsInOrderCallbackReq;
import com.loukou.lkt.lkt.req.WmsInOrderNoticeDetailReq;
import com.loukou.lkt.lkt.req.WmsInOrderNoticeReq;
import com.loukou.lkt.lkt.resp.PageModel;
import com.loukou.lkt.lkt.resp.PoPurchaseOrderDetailRespDto;
import com.loukou.lkt.lkt.resp.PoPurchaseOrderGoodsDto;
import com.loukou.lkt.lkt.resp.PoPurchaseOrderLogDto;
import com.loukou.lkt.lkt.resp.PurchaseGoodsHistoryPriceDto;
import com.loukou.lkt.lkt.resp.PurchaseOrderListDto;
import com.loukou.lkt.lkt.resp.RespDto;
import com.loukou.lkt.lkt.resp.WmsNoticeRespDto;
import com.loukou.lkt.lkt.service.GoodsStockService;
import com.loukou.lkt.lkt.service.OrderOperateLogService;
import com.loukou.lkt.lkt.service.PoPurchaseOrderService;
import com.loukou.lkt.lkt.service.SerialNumberService;
import com.loukou.lkt.lkt.service.SupplierGoodsService;
import com.loukou.lkt.lkt.service.SupplierService;
import com.loukou.lkt.lkt.utils.PostUtils;

@Service
public class PoPurchaseOrderServiceImpl implements PoPurchaseOrderService{
	
	@Autowired
	private PoPurchaseOrderDao poPurchaseOrderDao;
	@Autowired
	private PoPurchaseOrderDetailDao poPurchaseOrderDetailDao;
	@Autowired
	private StockInOrderDao stockInOrderDao;
	@Autowired
	private StockInOrderDetailDao stockInOrderDetailDao;
	@Autowired
	private WarehouseDao warehouseDao;
	
	@Autowired
	private SupplierService supplierService;
	
	@Autowired
	private SupplierDao supplierDao;
	
	@Autowired
	private GoodsStockDao goodsStockDao;
	
	@Autowired
	private GoodsDao goodsDao;
	
//	@Autowired
//	private GoodsDao goodsSpecDao;
	
	@Autowired
	private SupplierGoodsService supplierGoodsService;
	
	@Autowired
	private OrderOperateLogService orderOperateLogService;
	
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private SerialNumberService serialNumberService;
	
	@Autowired
	private GoodsCostDao goodsCostDao;
	
	@Autowired
	private GoodsStockService stockService;
	
	@Autowired
	private UserSupplierDao userSupplierDao;

	@Override
	public RespDto<List<PurchaseOrderListDto>> getSupplierOrdersInfo(int userId) {
		
		if(userId < 1) {
			return new RespDto<List<PurchaseOrderListDto>>(401, "参数有误");
		}
		
		RespDto<List<PurchaseOrderListDto>> resp = new RespDto<List<PurchaseOrderListDto>>(200, "");
		
		List<PurchaseOrderListDto> result = new ArrayList<PurchaseOrderListDto>();
		
		List<UserSupplier> userSuppliers = userSupplierDao.findByUserId(userId);
		List<Integer> supplierIds = new ArrayList<Integer>();
		for(UserSupplier u : userSuppliers) {
			supplierIds.add(u.getSupplierId());
		}
		
		RespDto<List<Supplier>> suppliers = supplierService.getByIsUseAndIsExamineAndIds(
				SupplierIsInUseEnum.TYPE_YES.getType(), 
				SupplierIsExamineEnum.TYPE_YES.getType(),
				supplierIds);
		if(suppliers.getCode() == 401) {
			return new RespDto<List<PurchaseOrderListDto>>(401, suppliers.getMsg());
		} else if(suppliers.getCode() == 400) {
			return new RespDto<List<PurchaseOrderListDto>>(400, suppliers.getMsg());
		}
		
		generateSupplierOrdersResult(suppliers.getResult(), result);
		resp.setResult(result);
		return resp;
	}
	
	private void generateSupplierOrdersResult(
			List<Supplier> suppliers, 
			List<PurchaseOrderListDto> result) {
		
		fillSupplierOrderListDto(result, suppliers);
		
//		result.setData(dtoList);
//		result.setPageNo(pageNum);
//		result.setPageSize(pageSize);
//		result.setTotalPageNum(suppliers.getTotalPages());
//		result.setRecordNum((int)suppliers.getTotalElements());
//		result.setRecordsFiltered((int)suppliers.getTotalElements());
	}
	
	private void fillSupplierOrderListDto(List<PurchaseOrderListDto> dtoList, 
			List<Supplier> supplierList) {
		Map<Integer, List<PoPurchaseOrder>> supplierOrderMap = getSupplierOrderMap(supplierList);
		
		List<Integer> sIds = new ArrayList<Integer>();
		for(Supplier supplier:supplierList){
			sIds.add(supplier.getId());
			
			PurchaseOrderListDto dto = new PurchaseOrderListDto();
			dto.setSupplierId(supplier.getId());
			dto.setSupplierCode(supplier.getSupplierCode());
			dto.setSupplierName(supplier.getSupplierName());
			dtoList.add(dto);
		}
		if(sIds.size()==0){
			return;
		}
		
		
		List<Integer> supplierIds = new ArrayList<Integer>();
		supplierIds.addAll(supplierOrderMap.keySet());
		List<SupplierGoods> supplierGoods = supplierGoodsService.getGoodsBySupplierIds(supplierIds);
		
		if(CollectionUtils.isEmpty(supplierGoods)) {
			return;
		}
		
		Map<Integer, List<SupplierGoods>> supplierGoodsMap = new HashMap<Integer, List<SupplierGoods>>();
		
		for(SupplierGoods g : supplierGoods) {
			if(supplierGoodsMap.containsKey(g.getSupplierId())) {
				List<SupplierGoods> sGoods = supplierGoodsMap.get(g.getSupplierId());
				sGoods.add(g);
			} else {
				List<SupplierGoods> sGoods = new ArrayList<SupplierGoods>();
				sGoods.add(g);
				supplierGoodsMap.put(g.getSupplierId(), sGoods);
			}
		}
		
		for(Map.Entry<Integer, List<PoPurchaseOrder>> entry: supplierOrderMap.entrySet()) {
			for(Supplier s : supplierList) {
				PurchaseOrderListDto dto = new PurchaseOrderListDto();
				if(s.getId() == entry.getKey()) {
					Map<String, Integer> map = getStateOrderNum(entry.getValue());
					dto.setSupplierId(s.getId());
					dto.setSupplierCode(s.getSupplierCode());
					dto.setSupplierName(s.getSupplierName());
					dto.setReceivedNum(map.get("received"));
					dto.setUnreceivedNum(map.get("unreceived"));
					dto.setTotalNum(map.get("total"));
					
					dtoList.add(dto);
				}
				
				for(Map.Entry<Integer, List<SupplierGoods>> e : supplierGoodsMap.entrySet()) {
					if(e.getKey() == s.getId()) {
						dto.setSkuNum(e.getValue().size());
					}
				}
			}
		}	
	}
	
	/**
	 * supplierId, orderList
	 * @param supplierList
	 * @return
	 */
	private Map<Integer, List<PoPurchaseOrder>> getSupplierOrderMap(List<Supplier> supplierList) {

		Map<Integer, List<PoPurchaseOrder>> supplierOrderMap = new HashMap<Integer, List<PoPurchaseOrder>>();
		List<Integer> supplierIdList = new ArrayList<Integer>();
		for(Supplier s : supplierList) {
			supplierIdList.add(s.getId());
		}
		
		List<PoPurchaseOrder> PoPurchaseorderList = 
				(List<PoPurchaseOrder>)poPurchaseOrderDao.findBySupplierIdIn(supplierIdList);
		if(CollectionUtils.isEmpty(PoPurchaseorderList)) {
			return supplierOrderMap;
		}
		
		
		for(PoPurchaseOrder dto : PoPurchaseorderList) {
			if(supplierOrderMap.containsKey(dto.getSupplierId())) {
				List<PoPurchaseOrder> purchaseorderlist = supplierOrderMap.get(dto.getSupplierId());
				purchaseorderlist.add(dto);
			} else {
				List<PoPurchaseOrder> purchaseorderlist = new ArrayList<PoPurchaseOrder>();
				purchaseorderlist.add(dto);
				supplierOrderMap.put(dto.getSupplierId(), purchaseorderlist);
			}
		}
		
		return supplierOrderMap;
	}
	
	private Map<String, Integer> getStateOrderNum(List<PoPurchaseOrder> purchaseorderlist) {
		Map<String, Integer> result = new HashMap<String, Integer>();
		int totalNum = 0;
		int receivedNum = 0;
		int unreceivedNum = 0;
		
		for(PoPurchaseOrder dto : purchaseorderlist) {
			if(dto.getOrderState() == PoPurchaseorderStateEnum.STATE_RECEIVED.getState() ||
					dto.getOrderState() == PoPurchaseorderStateEnum.STATE_CLOSED.getState()) {
				receivedNum += 1;
			} else if(dto.getOrderState() == PoPurchaseorderStateEnum.STATE_DEPART_CHECKED.getState() ||
					dto.getOrderState() == PoPurchaseorderStateEnum.STATE_NOTIFIED.getState()) {
				unreceivedNum += 1;
			}
		}
		totalNum = receivedNum + unreceivedNum;
		result.put("total", totalNum);
		result.put("received", receivedNum);
		result.put("unreceived", unreceivedNum);
		
		return result;
	}
	
	/**
	 * 更新采购单
	 */
	@Override
	@Transactional
	public RespDto<String> updatePurchase(int stockInOrderId,WmsInOrderCallbackReq req) {
		RespDto<String> resp = new RespDto<String>();
		if(req == null){
			resp.setCode(401);
			resp.setMsg("参数为空");
			return resp;
		}
		
		//获取采购单
		PoPurchaseOrder poPurchaseorder=poPurchaseOrderDao.findByOrderCode(req.getOutbizCode());
		if(poPurchaseorder == null){
			resp.setCode(402);
			resp.setMsg("采购单不存在");
			return resp;
		}
		
		//更新采购单
		poPurchaseOrderDao.updatePoPurchaseOrderForApi(poPurchaseorder.getId(), stockInOrderId, req.getReceiveTime(), PoPurchaseorderStateEnum.STATE_NOTIFIED.getState(), req.getReceiveUserName(), req.getReceiveTime());

		for(WmsInOrderCallbackDetailReq inOrderDetail:req.getDetails()){
			//更新采购单明细
			poPurchaseOrderDetailDao.updateReceiveNumberForApi(Integer.parseInt(inOrderDetail.getOutbizId()), inOrderDetail.getReceiveNumber());
		}
		
		OrderOperateLog savedLog = orderOperateLogService.saveOrderOperateLog(OrderOperateLogTypeEnum.TYPE_STATE_CHANGE, poPurchaseorder.getOrderCode(), 0, "system", "system");
		if(null == savedLog) {
			return new RespDto<String>(500, "采购单状态操作日志失败");
		}

		resp.setMsg("更新完成");
		return resp;
	}
	
	/**
	 * 推送采购入库通知到WMS
	 */
	@Override
	public RespDto<String> sendPurchaseOrderToWms(int purchaseOrderId) {
		RespDto<String> resp = new RespDto<String>();
		//获取采购单
		PoPurchaseOrder poPurchaseOrderDto=poPurchaseOrderDao.findOne(purchaseOrderId);
		if(poPurchaseOrderDto == null){
			resp.setCode(401);
			resp.setResult(purchaseOrderId + "未找到对应采购单");
			return resp;
		}
		
		//获取仓库信息
		Warehouse warehouseDto=warehouseDao.findOne(poPurchaseOrderDto.getWarehouseId());
		
		//LKT根据采购单通知WMS入库
		WmsInOrderNoticeReq wmsInOrderNotice = new WmsInOrderNoticeReq();
		wmsInOrderNotice.setOutbizCode(""+poPurchaseOrderDto.getOrderCode());
		wmsInOrderNotice.setWarehouseNo(""+warehouseDto.getWarehouseCode());
		wmsInOrderNotice.setRemark(poPurchaseOrderDto.getRemark());
		wmsInOrderNotice.setOrderType(StockInOrderTypeEnum.TYPE_PURCHASE.getType());
		
		//获取采购明细列表
		List<PoPurchaseOrderDetail> poPurchaseOrderDetailList = poPurchaseOrderDetailDao.findByOrderId(purchaseOrderId);
		if(poPurchaseOrderDetailList == null || poPurchaseOrderDetailList.size() <= 0){
			resp.setCode(402);
			resp.setResult(purchaseOrderId + "采购单明细不存在");
			return resp;
		}
		
		List<WmsInOrderNoticeDetailReq> wmsInOrderNoticeDetailList = new ArrayList<WmsInOrderNoticeDetailReq>();
		for(PoPurchaseOrderDetail orderDetail : poPurchaseOrderDetailList){
			WmsInOrderNoticeDetailReq inDetailReq = new WmsInOrderNoticeDetailReq();
			inDetailReq.setOutbizId(""+orderDetail.getId());
			inDetailReq.setCustomerGoodsId(""+orderDetail.getGoodsId());
			inDetailReq.setGoodsName(orderDetail.getGoodsName());
			inDetailReq.setBarcode(orderDetail.getBn());
			inDetailReq.setQuantity(orderDetail.getOrderNumber());
			wmsInOrderNoticeDetailList.add(inDetailReq);
		}
		wmsInOrderNotice.setDetails(wmsInOrderNoticeDetailList);
		
		//通知仓库
		Object wmsInOrder=PostUtils.postData(Urls.LktTellWmsInOrderNotice, wmsInOrderNotice);
		if(wmsInOrder == null){
			resp.setCode(403);
			resp.setResult("通知WMS入库失败");
			return resp;
		}
		WmsNoticeRespDto wmsResp = (WmsNoticeRespDto)wmsInOrder;
		if(!"200".equals(wmsResp.getCode())){
			resp.setCode(Integer.valueOf(wmsResp.getCode()));
			resp.setResult(wmsResp.getSuccess());
			resp.setMsg(wmsResp.getErrorMsg());
			return resp;
		}
		//更新采购单状态为已通知
		poPurchaseOrderDao.updateOrderStateById(PoPurchaseorderStateEnum.STATE_NOTIFIED.getState(),purchaseOrderId);
		
		return resp;
	}

	@Override
	public RespDto<List<PurchaseOrderListDto>> getSupplierOrdersInfoBySupplierName(
			String supplierName) {
		if(StringUtils.isBlank(supplierName)) {
			return new RespDto<List<PurchaseOrderListDto>>(401, "参数有误");
		}
		
		RespDto<List<Supplier>> suppliers = supplierService.getBySupplierName(supplierName,
				SupplierIsInUseEnum.TYPE_YES.getType(), 
				SupplierIsExamineEnum.TYPE_YES.getType());
		
		if(suppliers.getCode() == 401) {
			return new RespDto<List<PurchaseOrderListDto>>(401, suppliers.getMsg());
		} else if(suppliers.getCode() == 400) {
			return new RespDto<List<PurchaseOrderListDto>>(400, suppliers.getMsg());
		}

		RespDto<List<PurchaseOrderListDto>> resp = new RespDto<List<PurchaseOrderListDto>>(200, "");
		
		List<PurchaseOrderListDto> result = new ArrayList<PurchaseOrderListDto>();
		resp.setResult(result);
		
		generateSupplierOrdersResult(suppliers.getResult(), result);
		
		return resp;
	}

	@Override
	public RespDto<List<PurchaseOrderListDto>> getSupplierOrdersInfoBySupplierCode(
			String supplierCode) {
		if(StringUtils.isBlank(supplierCode)) {
			return new RespDto<List<PurchaseOrderListDto>>(401, "参数有误");
		}
		
		RespDto<List<Supplier>> suppliers = supplierService.getBySupplierCode(supplierCode,
				SupplierIsInUseEnum.TYPE_YES.getType(), 
				SupplierIsExamineEnum.TYPE_YES.getType());
		
		if(suppliers.getCode() == 401) {
			return new RespDto<List<PurchaseOrderListDto>>(401, suppliers.getMsg());
		} else if(suppliers.getCode() == 400) {
			return new RespDto<List<PurchaseOrderListDto>>(400, suppliers.getMsg());
		}
		
		RespDto<List<PurchaseOrderListDto>> resp = new RespDto<List<PurchaseOrderListDto>>(200, "");
		
		List<PurchaseOrderListDto> result = new ArrayList<PurchaseOrderListDto>();
		resp.setResult(result);
		
		generateSupplierOrdersResult(suppliers.getResult(), result);
		
		return resp;
	}

	@Override
	public RespDto<PageModel<PurchaseGoodsHistoryPriceDto>> getGoodsPurchaseHistoryByTaosku(
			String taosku, String bn, String goodsName,int pageNum, int pageSize) {
		if(StringUtils.isBlank(taosku) || pageNum < 1 || pageSize < 1) {
			return new RespDto<PageModel<PurchaseGoodsHistoryPriceDto>>(401, "参数有误");
		}
		
		Sort sort = new Sort(Direction.DESC, "orderId");
		Pageable pageable = new PageRequest(pageNum - 1, pageSize, sort);
		Page<PoPurchaseOrderDetail> PoPurchaseorderDetails = poPurchaseOrderDetailDao.findByTaosku(taosku, pageable);
		
		if(PoPurchaseorderDetails.getTotalElements() == 0) {
			return new RespDto<PageModel<PurchaseGoodsHistoryPriceDto>>(
					400, String.format("没有采购过货号为%s的商品", taosku));
		}
		
		List<Integer> poPurchaseOrderIds = new ArrayList<Integer>();
		
		for(PoPurchaseOrderDetail d : PoPurchaseorderDetails) {
			poPurchaseOrderIds.add(d.getOrderId());
		}
		List<PoPurchaseOrder> poPurchaseOrderList = (List<PoPurchaseOrder>)poPurchaseOrderDao.findAll(poPurchaseOrderIds);
				
		List<Integer> supplierIds = new ArrayList<Integer>();
		for(PoPurchaseOrder p : poPurchaseOrderList) {
			supplierIds.add(p.getSupplierId());
		}
		
		RespDto<List<Supplier>> suppliers = supplierService.getBySupplierIds(supplierIds);
		
		if(suppliers.getCode() == 401) {
			return new RespDto<PageModel<PurchaseGoodsHistoryPriceDto>>(401, suppliers.getMsg());
		} else if(suppliers.getCode() == 400) {
			return new RespDto<PageModel<PurchaseGoodsHistoryPriceDto>>(400, suppliers.getMsg());
		}
		
		List<Supplier> supplierList = suppliers.getResult();
		List<PurchaseGoodsHistoryPriceDto> dtoList = new ArrayList<PurchaseGoodsHistoryPriceDto>();
		
		for(PoPurchaseOrderDetail d : PoPurchaseorderDetails) {
			PurchaseGoodsHistoryPriceDto dto = new PurchaseGoodsHistoryPriceDto();
			for(PoPurchaseOrder o : poPurchaseOrderList) {
				if(d.getOrderId() == o.getId()) {
					dto.setBn(bn);
					dto.setGoodsName(goodsName);
					dto.setOrderCode(o.getOrderCode());
					dto.setPurchaseDate(o.getReceiveTime());
					dto.setReceiveNum(d.getReceiveNumber());
					dto.setRemark(d.getRemark());
					dto.setTaosku(taosku);
					dto.setTaxPrice(d.getTaxPrice());
				}
				
				for(Supplier s : supplierList) {
					if(s.getId() == o.getSupplierId()) {
						dto.setSupplierCode(s.getSupplierCode());
						dto.setSupplierName(s.getSupplierName());
					}
				}
			}
			dtoList.add(dto);
		}
		
		PageModel<PurchaseGoodsHistoryPriceDto> result = new PageModel<PurchaseGoodsHistoryPriceDto>(
				pageNum, pageSize, 
				PoPurchaseorderDetails.getTotalPages(), 
				PoPurchaseorderDetails.getTotalElements());
		
		result.setRecordsFiltered(PoPurchaseorderDetails.getTotalElements());
		result.setData(dtoList);
		RespDto<PageModel<PurchaseGoodsHistoryPriceDto>> resp = new RespDto<PageModel<PurchaseGoodsHistoryPriceDto>>(200, "");
		resp.setResult(result);
		return resp;
	}

	@Override
	public RespDto<String> submitPurchaseOrder(PurchaseOrderReqDto dto) {
		PoPurchaseOrder order = new PoPurchaseOrder();
		BeanUtils.copyProperties(dto, order);
		order.setOrderState(PoPurchaseorderStateEnum.STATE_UNCHECK.getState());
		String orderCode = serialNumberService.generateNewVoucherCode(
				VoucherPrefixEnum.PREFIX_PURCHASE_ORDER, dto.getWarehouseId());
		order.setOrderCode(orderCode);
		PoPurchaseOrder savedOrder = poPurchaseOrderDao.save(order);
		
		if(null == savedOrder) {
			return new RespDto<String>(500, "保存采购单失败");
		}
		
		List<PurchaseOrderDetailDto> details = dto.getDetails();
		List<PoPurchaseOrderDetail> detailList = new ArrayList<PoPurchaseOrderDetail>();
		for(PurchaseOrderDetailDto d : details) {
			PoPurchaseOrderDetail pd = new PoPurchaseOrderDetail();
			BeanUtils.copyProperties(d, pd);
			pd.setOrderId(savedOrder.getId());
			detailList.add(pd);
		}
		List<PoPurchaseOrderDetail> savedDetailList = (List<PoPurchaseOrderDetail>) poPurchaseOrderDetailDao.save(detailList);
		
		if(CollectionUtils.isEmpty(savedDetailList)) {
			return new RespDto<String>(500, "保存采购单详情失败");
		}
		
		User user = userDao.findOne(dto.getUserId());
		if(null == user) {
			return new RespDto<String>(401, "没有该用户");
		}
		OrderOperateLog savedLog = orderOperateLogService.saveOrderOperateLog(OrderOperateLogTypeEnum.TYPE_NEW, 
				savedOrder.getOrderCode(), dto.getUserId(), user.getUsername(), user.getRealName());
		
		if(null == savedLog) {
			return new RespDto<String>(500, "保存采购单操作日志失败");
		}
		return new RespDto<String>(200, "");
	}

	@Override
	public PoPurchaseOrderDetailRespDto getPurchaseOrderDetail(String orderCode) {
		
		PoPurchaseOrderDetailRespDto respDto = new PoPurchaseOrderDetailRespDto();

		fillData(orderCode, respDto);
		
		List<PoPurchaseOrderLogDto> logList = new ArrayList<PoPurchaseOrderLogDto>();
		respDto.setLog(logList);
		fillLog(orderCode, logList);
		
		return respDto;
	}
	
	private void fillLog(String orderCode, List<PoPurchaseOrderLogDto> logList) {
		List<OrderOperateLog> logs = orderOperateLogService.findByOrderCode(orderCode);
		
		for(OrderOperateLog l : logs) {
			PoPurchaseOrderLogDto dto = new PoPurchaseOrderLogDto();
			dto.setUserId(l.getUserId());
			dto.setUserName(l.getUserName());
			dto.setRealName(l.getRealName());
			dto.setCreateTime(l.getCreateTime());
			dto.setAction(l.getAction());
			logList.add(dto);
		}
	}

	private void fillData(String orderCode, PoPurchaseOrderDetailRespDto respDto) {
		
		PoPurchaseOrder order = poPurchaseOrderDao.findByOrderCode(orderCode);
		
		if(order == null) {
			return;
		}
		
		List<PoPurchaseOrderDetail> orderDetail = poPurchaseOrderDetailDao.findByOrderId(order.getId());

		if(CollectionUtils.isEmpty(orderDetail)) {
			return;
		}
		
		Supplier supplier = supplierDao.findOne(order.getSupplierId());
		
		if(supplier == null) {
			return;
		}
		
		List<Integer> goodsIds = new ArrayList<Integer>();
//		List<Integer> specIds = new ArrayList<Integer>();
		for(PoPurchaseOrderDetail d : orderDetail) {
			goodsIds.add(d.getGoodsId());
//			specIds.add(d.getGoodsSpecId());
		}
		
		Warehouse warehouse = warehouseDao.findOne(order.getWarehouseId());
		
		if(warehouse == null) {
			return;
		}
		
		//获取商品库存
		Map<Integer, Integer> goodsIdAvaliableStockMap = caculateAvaliableGoodsNum(goodsIds, order.getWarehouseId());
		
//		List<GoodsSpec> goodsSpecList = goodsSpecDao.findBySpecIdIn(specIds);
		
		List<Goods> goodsList = (List<Goods>) goodsDao.findAll(goodsIds);
		
		respDto.setId(order.getId());
		respDto.setOrderCode(orderCode);
		respDto.setSupplierId(supplier.getId());
		respDto.setSupplierName(supplier.getSupplierName());
		respDto.setWarehouseId(warehouse.getWarehouseId());
		respDto.setWarehouseName(warehouse.getWarehouseName());
		respDto.setSettmentType(supplier.getSettmentType());
		respDto.setSettmentName(SettlementTypeEnum.parseSettlementTypeEnum(supplier.getSettmentType()).getName());
		respDto.setPrePayAmount(order.getPrepayAmount());
		respDto.setDiscount(order.getDiscount());
		respDto.setTotalAmount(getTotalAmount(orderDetail, order.getDiscount()));
		respDto.setPurchaseDate(order.getCreateTime());
		respDto.setPlanArrivetime(order.getPlanArrivetime());
		respDto.setAddress(order.getAddress());
		respDto.setRemark(order.getRemark());
		List<PoPurchaseOrderGoodsDto> orderGoodsDtoList = new ArrayList<PoPurchaseOrderGoodsDto>();
		respDto.setOrderGoodsDtoList(orderGoodsDtoList);
		//fill orderGoodsDtoList
		for(PoPurchaseOrderDetail d : orderDetail) {
	
			PoPurchaseOrderGoodsDto orderGoodsDto = new PoPurchaseOrderGoodsDto();
			orderGoodsDto.setDiscount(order.getDiscount());
			
			orderGoodsDto.setTaosku(d.getTaosku());
			orderGoodsDto.setBn(d.getBn());
			orderGoodsDto.setGoodsName(d.getGoodsName());
			orderGoodsDto.setDeliveryNum(d.getOrderNumber() - d.getReceiveNumber());
			for(Map.Entry<Integer, Integer> entry : goodsIdAvaliableStockMap.entrySet()) {
				if(entry.getKey() == d.getGoodsId()) {
					orderGoodsDto.setAvailableNum(entry.getValue());//可用库存的计算方法
				}
			}
			orderGoodsDto.setSaleNumPerWeek(0);//TODO mock
			for(Goods gs : goodsList) {
				orderGoodsDto.setSalePrice(gs.getSalePrice());
				orderGoodsDto.setSizeSpec(gs.getPacking());//箱规
				if(gs.getGoodsId() == d.getGoodsId()) {
					orderGoodsDto.setTaxRate(gs.getTax());
				}
			}
			double recentPurchasePrice = getRecentPurchasePrice(d.getTaosku());
			orderGoodsDto.setRecentPurchasePrice(recentPurchasePrice);
			orderGoodsDto.setPurchasePrice(d.getTaxPrice());
			orderGoodsDto.setDiscountRate(d.getDiscountRate());
	
			orderGoodsDto.setPurchaseNum(d.getOrderNumber());
			double goodsAmount = caculateGoodsAmount(d.getTaxPrice(), d.getDiscountRate(), d.getOrderNumber());
			orderGoodsDto.setGoodsAmount(goodsAmount);
			
			orderGoodsDtoList.add(orderGoodsDto);
		}
	}
	
	private double getTotalAmount(List<PoPurchaseOrderDetail> orderDetail, double discount) {
		double totalAmount = 0;
		for(PoPurchaseOrderDetail d : orderDetail) {
			totalAmount += d.getTaxPrice() * d.getDiscountRate() * d.getOrderNumber();
		}
		
		return totalAmount - discount;
	}
	
	private double getRecentPurchasePrice(String taosku) {
		Sort sort = new Sort(Direction.DESC, "id");
		Pageable pageable = new PageRequest(0, 1, sort);
		PoPurchaseOrderDetail poPurchaseOrderDetail = poPurchaseOrderDetailDao.findByTaosku(taosku, pageable).getContent().get(0);
		if(null != poPurchaseOrderDetail) {
			return poPurchaseOrderDetail.getTaxPrice();
		}
		return 0;
	}
	
	private double caculateGoodsAmount(double taxPrice, double discountRate, int orderNumber) {
		//金额小计（自动计算）：采购价*折扣率*订购数量
		return taxPrice * discountRate * orderNumber;
	}

	@Override
	@Transactional
	public RespDto<String> editPurchaseOrder(PoPurchaseOrderDetailReqDto reqDto) {

		poPurchaseOrderDao.updateOrder(reqDto.getId(), reqDto.getPrePayAmount(), reqDto.getDiscount(), 
				reqDto.getPlanArrivetime(), reqDto.getAddress(), reqDto.getRemark(), 
				reqDto.getWarehouseId(), reqDto.getSettmentType());
		
		orderOperateLogService.saveOrderOperateLog(OrderOperateLogTypeEnum.TYPE_EDIT, reqDto.getOrderCode(), 
				reqDto.getUserId(), reqDto.getUserName(), reqDto.getRealName());
		
		List<PoPurchaseOrderGoodsDto> orderGoodsList = reqDto.getOrderGoodsDtoList();
		
		updatePoPurchaseOrderDetail(orderGoodsList, reqDto.getId());
		return null;
	}
	
	@Transactional
	private void updatePoPurchaseOrderDetail(List<PoPurchaseOrderGoodsDto> orderGoodsList, int orderId) {
		List<PoPurchaseOrderDetail> details = poPurchaseOrderDetailDao.findByOrderId(orderId);
		
		for(PoPurchaseOrderGoodsDto dto : orderGoodsList) {
			
			for(PoPurchaseOrderDetail detail : details) {
				if(StringUtils.equals(detail.getTaosku(), dto.getTaosku())) {
					
					double goodsAmount = caculateGoodsAmount(dto.getPurchasePrice(), 
							dto.getDiscountRate(), dto.getPurchaseNum());
					poPurchaseOrderDetailDao.updateDetailForEdit(detail.getId(), dto.getPurchasePrice(),
							dto.getDiscountRate(), dto.getPurchaseNum(), goodsAmount);
				}
			}
		}
	}

	@Override
	public PoPurchaseOrderDetailRespDto getSupplierGoodsInfo(int supplierId, int warehouseId) {
		List<SupplierGoods> supplierGoods = supplierGoodsService.getSupplierGoods(supplierId);
		PoPurchaseOrderDetailRespDto resp = new PoPurchaseOrderDetailRespDto();
		Supplier supplier = supplierDao.findOne(supplierId);
		if(null == supplier) {
			return new PoPurchaseOrderDetailRespDto();
		}
		resp.setSupplierId(supplierId);
		resp.setSupplierName(supplier.getSupplierName());
		resp.setSettmentType(supplier.getSettmentType());
		resp.setSettmentName(SettlementTypeEnum.parseSettlementTypeEnum(supplier.getSettmentType()).getName());
		
		List<PoPurchaseOrderGoodsDto> orderGoodsDtoList = new ArrayList<PoPurchaseOrderGoodsDto>();
		
		fillInitData(orderGoodsDtoList, supplierGoods, warehouseId, supplierId);
		
		resp.setOrderGoodsDtoList(orderGoodsDtoList);
		return resp;
	}

	/**
	 * 采购商品选择，供应商商品列表
	 * @param respDto
	 */
	private void fillInitData(List<PoPurchaseOrderGoodsDto> orderGoodsDtoList, 
			List<SupplierGoods> supplierGoods, int warehouseId, int supplierId) {
		
		List<Integer> goodsIds = new ArrayList<Integer>();
//		List<Integer> specIds = new ArrayList<Integer>();
		
		for(SupplierGoods sg : supplierGoods) {
			goodsIds.add(sg.getGoodsId());
//			specIds.add(sg.getSpecId());	
		}
		
//		Warehouse warehouse = warehouseDao.findOne(warehouseId);
		
		Map<Integer, Integer> goodsIdAvaliableStockMap = caculateAvaliableGoodsNum(goodsIds, warehouseId);
		
		Map<Integer, Integer> goodsIdDelieverNumMap = caculateDelieverGoodsNum(goodsIds, warehouseId, supplierId);
				
		List<Goods> goodsList = (List<Goods>) goodsDao.findAll(goodsIds);
//		List<GoodsSpec> goodsSpecList = (List<GoodsSpec>) goodsSpecDao.findAll(specIds);
		
		for(SupplierGoods sg : supplierGoods) {
			PoPurchaseOrderGoodsDto dto = new PoPurchaseOrderGoodsDto();
			
			for(Map.Entry<Integer, Integer> entry : goodsIdDelieverNumMap.entrySet()) {
				if(entry.getKey() == sg.getGoodsId()) {
					dto.setDeliveryNum(entry.getValue());//未到货数量
				}
			}
			
			for(Map.Entry<Integer, Integer> entry : goodsIdAvaliableStockMap.entrySet()) {
				if(entry.getKey() == sg.getGoodsId()) {
					dto.setAvailableNum(entry.getValue());//可用库存的计算方法
				}
			}
			
			dto.setSaleNumPerWeek(0);//TODO mock
			for(Goods g : goodsList) {
				if(g.getGoodsId() == sg.getGoodsId()) {
					dto.setGoodsName(g.getGoodsName());
					dto.setTaxRate(g.getTax());
				}
			}
			for(Goods gs : goodsList) {
				if(gs.getGoodsId() == sg.getGoodsId()) {
					dto.setSalePrice(gs.getSalePrice());
					dto.setSizeSpec(gs.getPacking());
					dto.setTaosku(gs.getSku());
					dto.setBn(gs.getBarcode());
				}
			}

			dto.setRecentPurchasePrice(caculateRecentPurchasePrice(sg.getGoodsId()));
			//默认显示此供应商最近一次采购价（必须已到货）
			dto.setPurchasePrice(caculateRecentSupplierPrice(sg.getGoodsId(), supplierId));
			orderGoodsDtoList.add(dto);
		}
		
		
	}
	
	/**
	 *TODO
	 * @param specId
	 * @param supplierId
	 * @return 供应商范围最近一次采购价（必须已到货）
	 */
	private double caculateRecentSupplierPrice(int specId, int supplierId) {
//		supplierGoodsService.
		return 0;
	}
	
	/**
	 * 
	 * @param goodsId
	 * @return 所有供应商范围最近一次采购价（必须已到货）
	 */
	private double caculateRecentPurchasePrice(int goodsId) {
		PoPurchaseOrderDetail d = poPurchaseOrderDetailDao.findOneByGoodsId(goodsId);
		return d.getTaxPrice();
	}
	
	/**
	 *  未到货数量：订购数量-收货数量
	 * @param goodsIds
	 * @param warehouseId
	 * @return 未到货数量
	 */
	private Map<Integer, Integer> caculateDelieverGoodsNum(List<Integer> goodsIds, int warehouseId, int supplierId) {
		
		//TODO 加入订单状态
		List<PoPurchaseOrder> poPurchaseOrderList = poPurchaseOrderDao.findBySupplierIdAndWarehouseId(
				supplierId, warehouseId);
	
		List<Integer> orderIds = new ArrayList<Integer>();
		
		for(PoPurchaseOrder o : poPurchaseOrderList) {
			orderIds.add(o.getId());
		}
		
		List<PoPurchaseOrderDetail> details = poPurchaseOrderDetailDao.findByOrderIdIn(orderIds);
		
		Map<Integer, Integer> goodsIdDelieverNumMap = new HashMap<Integer, Integer>();
		for(PoPurchaseOrderDetail d : details) {
			int delieverNum = d.getOrderNumber() - d.getReceiveNumber();
			goodsIdDelieverNumMap.put(d.getGoodsId(), delieverNum);
		}
		
		return goodsIdDelieverNumMap;
	}
	
	/**
	 * FIXME 可用库存的计算方法
	 * @param goodsIds
	 * @param warehouseId
	 * @return
	 */
	private Map<Integer, Integer> caculateAvaliableGoodsNum(List<Integer> goodsIds, int warehouseId) {
		
		//获取商品库存
		List<GoodsStock> goodsStockList = goodsStockDao.findByWarehouseIdAndPositionTypeAndStockStateAndGoodsIdIn(
						warehouseId, PositionTypeEnum.TYPE_Normal.getId(), 
						GoodsStockStateEnum.STATE_Normal.getId(), goodsIds);
		Map<Integer, Integer> goodsIdAvaliableStockMap = new HashMap<Integer, Integer>();
		for(GoodsStock gs : goodsStockList) {
			goodsIdAvaliableStockMap.put(gs.getGoodsId(), gs.getStock());
		}
		return goodsIdAvaliableStockMap;
	}

	@Override
	public List<PoPurchaseOrderGoodsDto> addGoodsToPurchaseOrder(
			List<String> taoskus, int supplierId, int warehouseId) {
		List<Goods> goods= goodsDao.findBySkuIn(taoskus);
		if(CollectionUtils.isEmpty(goods)) {
			return new ArrayList<PoPurchaseOrderGoodsDto>();
		}
		
//		List<Integer> goodsSpecIds = new ArrayList<Integer>();
		List<Integer> goodsIds = new ArrayList<Integer>();
		for(Goods gs : goods) {
//			goodsSpecIds.add(gs.getSpecId());
			goodsIds.add(gs.getGoodsId());
		}
		
//		List<Goods> goodsList = (List<Goods>) goodsDao.findAll(goodsIds);
//		List<GoodsCost> goodsCostList = goodsCostDao.findBySpecIdIn(goodsSpecIds);//FIXME specids
		
		Map<Integer, Integer> goodsIdDelieverNumMap = caculateDelieverGoodsNum(goodsIds, warehouseId, supplierId);
		Map<Integer, Integer> goodsIdAvaliableStockMap = caculateAvaliableGoodsNum(goodsIds, warehouseId);
		
		List<PoPurchaseOrderGoodsDto> resp = new ArrayList<PoPurchaseOrderGoodsDto>();
		for(Goods gs : goods) {
			PoPurchaseOrderGoodsDto dto = new PoPurchaseOrderGoodsDto();
			dto.setGoodsId(gs.getGoodsId());
//			dto.setSpecId(gs.getSpecId());
			dto.setTaosku(gs.getSku());
			dto.setBn(gs.getBarcode());
			for(Map.Entry<Integer, Integer> entry : goodsIdDelieverNumMap.entrySet()) {
				if(entry.getKey() == gs.getGoodsId()) {
					dto.setDeliveryNum(entry.getValue());
				}
			}
			for(Map.Entry<Integer, Integer> entry : goodsIdAvaliableStockMap.entrySet()) {
				if(entry.getKey() == gs.getGoodsId()) {
					dto.setAvailableNum(entry.getValue());
				}
			}
			dto.setSalePrice(gs.getSalePrice());
			dto.setRecentPurchasePrice(caculateRecentPurchasePrice(gs.getGoodsId()));
			dto.setTaxRate(gs.getTax());
			
			dto.setSizeSpec(gs.getPacking());
			resp.add(dto);
		}
		
		return resp;
	}
	
}
